package textArea;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import javax.swing.KeyStroke;

import actions.Parentest;
import actions.ColumnModeAction;
import actions.writeHelloAction;

// NOTE: THIS CLASS IS OUTDATED AND HAS BEEN REPLACED BY KeyEventHandler.
// However, I'd like to keep it around. - Britt



/**
 * The KeyEventHandler invokes actions associated with the user's key strokes.
 * 
 * NOTE: The KeyEventHandler currently maps actions to KeyStrokes, this may be changed to map actions to
 * KeyEvent.VK values directly.
 * 
 * WARNING: The current system of mapping does not handle key combinations.
 * Only single keys may be mapped to actions, such as ENTER, SPACE, SHIFT, any letter, etc.
 */
public class OriginalKeyEventHandler extends KeyAdapter {
	
	/**
	 * Maps specific key strokes to a collection of actions that will be executed when the key stroke is detected.
	 */
	private Hashtable<KeyStroke, List<ActionListener>> keyBindings;
	
	/**
	 * Actions that will be executed when any key is typed.
	 */
	private List<ActionListener> keytypedActions;
	/**
	 * Actions that will be executed when any key is pressed
	 */
	private List<ActionListener> keypressedActions;
	
	/**
	 * Default constructor.
	 */
	public OriginalKeyEventHandler() {
		this.keyBindings = new Hashtable<KeyStroke, List<ActionListener>>();
		this.keytypedActions = new LinkedList<ActionListener>();
		this.keypressedActions = new LinkedList<ActionListener>();
		initDefaultBindings();
		initDefaultKeytypedActions();
		initKeypressedActions();
	}
	
	/**
	 * Sets up the default key bindings. 
	 */
	private void initDefaultBindings() {
		// Create a keystroke and use the addKeyBinding method to associate actions to that keystroke.
		// The second argument of getKeyStroke is always passed a 0 for this case.
		
		// ENTER Actions
		KeyStroke enterStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
		this.addKeyBinding(enterStroke, new writeHelloAction());
		
		
		// BACKSPACE Actions
		
		
		// ETC.
	}
	
	/**
	 * Sets up the Actions associated with the keyTyped event and not any particular key.
	 */
	private void initDefaultKeytypedActions() {
		// User the addKeyTypedAction to add actions that should be executed when any key is typed
		this.keytypedActions.add(new Parentest());
		
	}
	
	private void initKeypressedActions()
	{
		this.keypressedActions.add(new ColumnModeAction("Column Mode"));
	}
	
	/**
	 * Adds the passed action to the collection of actions that will be executed when
	 * any key is typed.
	 * @param action The action added to the collection of actions that will be executed when
	 * any key is typed.
	 */
	public void addKeyTypedAction(ActionListener action) {
		this.keytypedActions.add(action);
	}
	
	/**
	 * Creates an association between keyBinding and action.
	 * @param keyBinding The KeyStroke that will invoke action.
	 * @param action The Action invoked by the keyBinding KeyStroke.
	 */
	public void addKeyBinding(KeyStroke keyBinding, ActionListener action) {
		
		// If there is nothing bound to this key, add a new list
		// Otherwise add this action to the existing list
		List<ActionListener> list = this.keyBindings.get(keyBinding);
		
		if ( list == null ) {
			list = new LinkedList<ActionListener>();
			list.add(action);
			this.keyBindings.put(keyBinding, list);
		} else {
			list.add(action);
		}
		
	}
	
	@Override
	public void keyPressed(KeyEvent e)
	{
		executeKeyPressedActions(e);
	}
	
	@Override
	public void keyReleased(KeyEvent e) {
		
		// Execute the actions that happen regardless of what key was typed
		this.executeDefaultActions(e);
		
		// Get the actions associated with the key pressed and execute them
		this.executeKeyActions(e);
	}
	
	/**
	 * Invokes all actions that should execute when any key is typed.
	 * @param e The KeyEvent associated with the invoking of this method.
	 */
	public void executeDefaultActions(KeyEvent e) {
		Object source = e.getSource();
		for (ActionListener a : this.keytypedActions) {
			executeAction(a, source, null);
		}
	}
	
	public void executeKeyPressedActions(KeyEvent e)
	{
		Object source = e.getSource();
		for(ActionListener a : this.keypressedActions)
		{
			executeAction(a,source,""+e.getKeyChar());
		}
	}
	
	/**
	 * Invokes all actions that should execute when a specific key is typed.
	 * @param e The KeyEvent associated with the invoking of this method.
	 */
	public void executeKeyActions(KeyEvent e) {
		Object source = e.getSource();
		
		// Get the key typed
		char keyChar = e.getKeyChar();
		KeyStroke keyStroke = KeyStroke.getKeyStroke(keyChar, 0);
		
		// Execute all actions associated with this keyStroke
		List<ActionListener> list = this.keyBindings.get(keyStroke);
		if ( list != null ) {
			for ( ActionListener action : list ) {
				executeAction( action, source, null );
			}
		}
	}
	
	/**
	 * Invokes actionPerformed on action.
	 * @param action The actions to perform.
	 * @param source The source of the invoke.
	 * @param actionCommand The command associated with the parameter "action".
	 */
	public void executeAction(ActionListener action, Object source, String actionCommand) {
		ActionEvent evt = new ActionEvent(source, ActionEvent.ACTION_PERFORMED, actionCommand);
		action.actionPerformed(evt);
	}
}

